const state = {
  pending: "PENDING",
  fulfilled: "FULFILLED",
  rejected: "REJECTED",
};
class Promise {
  state = state.pending;
  value = undefined;
  reason = undefined;
  fulfilledCallbacks = [];
  rejectedCallbacks = [];
  constructor(exectur) {
    const resolve = (value) => {
      if (this.state === state.pending) {
        this.value = value;
        this.state = state.fulfilled;
        this.fulfilledCallbacks.forEach((fn) => fn());
      }
    };
    const reject = (reason) => {
      if (this.state === state.pending) {
        this.reason = reason;
        this.state = state.rejected;
        this.rejectedCallbacks.forEach((fn) => fn());
      }
    };
    exectur(resolve, reject);
  }

  then(onFufilled, onRejected) {
    const promise = new Promise((resolve, reject) => {
      if (this.state === state.fulfilled) {
        process.nextTick(() => {
          const x = onFufilled(this.value);
          resolvePromise(promise, x, resolve, reject);
        });
      }

      if (this.state === state.rejected) {
        process.nextTick(() => {
          const x = onRejected(this.reason);
          resolvePromise(promise, x, resolve, reject);
        });
      }

      if (this.state === state.pending) {
        this.fulfilledCallbacks.push(() => {
          process.nextTick(() => {
            const x = onFufilled(this.value);
            resolvePromise(promise, x, resolve, reject);
          });
        });
        this.rejectedCallbacks.push(() => {
          process.nextTick(() => {
            const x = onRejected(this.reason);
            resolvePromise(promise, x, resolve, reject);
          });
        });
      }
    });

    return promise;
  }
}

function resolvePromise(promise, x, resolve, reject) {
  if (promise === x) {
    throw new TypeError("123");
  }
  if ((typeof x === "object" && x != null) || typeof x === "function") {
    const then = x.then;
    if (typeof then === "function") {
      then.call(
        x,
        (y) => {
          resolve(y);
        },
        (r) => {
          reject(r);
        }
      );
    }
  }
  resolve(x);
}
export default Promise;
